﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.Serialization;
namespace NCS_CS
{
    public struct Complex : ICloneable, ISerializable
    {
        /// <summary>
        /// Real part of the complex number.
        /// </summary>
        public double Re;

        /// <summary>
        /// Imaginary part of the complex number.
        /// </summary>
        public double Im;

        /// <summary>
        ///  A double-precision complex number that represents zero.
        /// </summary>
        public static readonly Complex Zero = new Complex(0, 0);

        /// <summary>
        ///  A double-precision complex number that represents one.
        /// </summary>
        public static readonly Complex One = new Complex(1, 0);

        /// <summary>
        ///  A double-precision complex number that represents the squere root of (-1).
        /// </summary>
        public static readonly Complex I = new Complex(0, 1);

        /// <summary>
        /// Magnitude value of the complex number.
        /// </summary>
        /// 
        /// <remarks><para>Magnitude of the complex number, which equals to <b>Sqrt( Re * Re + Im * Im )</b>.</para></remarks>
        /// 
        public double Magnitude
        {
            get { return System.Math.Sqrt(Re * Re + Im * Im); }
        }

        /// <summary>
        /// Phase value of the complex number.
        /// </summary>
        /// 
        /// <remarks><para>Phase of the complex number, which equals to <b>Atan( Im / Re )</b>.</para></remarks>
        /// 
        public double Phase
        {
            get { return System.Math.Atan(Im / Re); }
        }

        /// <summary>
        /// Squared magnitude value of the complex number.
        /// </summary>
        public double SquaredMagnitude
        {
            get { return (Re * Re + Im * Im); }
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="Complex"/> class.
        /// </summary>
        /// 
        /// <param name="re">Real part.</param>
        /// <param name="im">Imaginary part.</param>
        /// 
        public Complex(double re, double im)
        {
            this.Re = re;
            this.Im = im;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Complex"/> class.
        /// </summary>
        /// 
        /// <param name="c">Source complex number.</param>
        /// 
        public Complex(Complex c)
        {
            this.Re = c.Re;
            this.Im = c.Im;
        }

        /// <summary>
        /// Adds two complex numbers.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the sum of specified
        /// complex numbers.</returns>
        /// 
        public static Complex Add(Complex a, Complex b)
        {
            return new Complex(a.Re + b.Re, a.Im + b.Im);
        }

        /// <summary>
        /// Adds scalar value to a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the sum of specified
        /// complex number and scalar value.</returns>
        /// 
        public static Complex Add(Complex a, double s)
        {
            return new Complex(a.Re + s, a.Im);
        }

        /// <summary>
        /// Adds two complex numbers and puts the result into the third complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Add(Complex a, Complex b, ref Complex result)
        {
            result.Re = a.Re + b.Re;
            result.Im = a.Im + b.Im;
        }

        /// <summary>
        /// Adds scalar value to a complex number and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Add(Complex a, double s, ref Complex result)
        {
            result.Re = a.Re + s;
            result.Im = a.Im;
        }

        /// <summary>
        /// Subtracts one complex number from another.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
        /// <param name="b">A <see cref="Complex"/> instance to be subtracted.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>a - b</b>).</returns>
        /// 
        public static Complex Subtract(Complex a, Complex b)
        {
            return new Complex(a.Re - b.Re, a.Im - b.Im);
        }

        /// <summary>
        /// Subtracts a scalar from a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
        /// <param name="s">A scalar value to be subtracted.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>a - s</b>).</returns>
        /// 
        public static Complex Subtract(Complex a, double s)
        {
            return new Complex(a.Re - s, a.Im);
        }

        /// <summary>
        /// Subtracts a complex number from a scalar value.
        /// </summary>
        /// 
        /// <param name="s">A scalar value to subtract from.</param>
        /// <param name="a">A <see cref="Complex"/> instance to be subtracted.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>s - a</b>).</returns>
        /// 
        public static Complex Subtract(double s, Complex a)
        {
            return new Complex(s - a.Re, a.Im);
        }

        /// <summary>
        /// Subtracts one complex number from another and puts the result in the third complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
        /// <param name="b">A <see cref="Complex"/> instance to be subtracted.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Subtract(Complex a, Complex b, ref Complex result)
        {
            result.Re = a.Re - b.Re;
            result.Im = a.Im - b.Im;
        }

        /// <summary>
        /// Subtracts a scalar value from a complex number and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
        /// <param name="s">A scalar value to be subtracted.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Subtract(Complex a, double s, ref Complex result)
        {
            result.Re = a.Re - s;
            result.Im = a.Im;
        }

        /// <summary>
        /// Subtracts a complex number from a scalar value and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="s">A scalar value to subtract from.</param>
        /// <param name="a">A <see cref="Complex"/> instance to be subtracted.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Subtract(double s, Complex a, ref Complex result)
        {
            result.Re = s - a.Re;
            result.Im = a.Im;
        }

        /// <summary>
        /// Multiplies two complex numbers.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
        /// 
        public static Complex Multiply(Complex a, Complex b)
        {
            // (x + yi)(u + vi) = (xu ?yv) + (xv + yu)i. 
            double aRe = a.Re, aIm = a.Im;
            double bRe = b.Re, bIm = b.Im;

            return new Complex(aRe * bRe - aIm * bIm, aRe * bIm + aIm * bRe);
        }

        /// <summary>
        /// Multiplies a complex number by a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
        /// 
        public static Complex Multiply(Complex a, double s)
        {
            return new Complex(a.Re * s, a.Im * s);
        }

        /// <summary>
        /// Multiplies two complex numbers and puts the result in a third complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Multiply(Complex a, Complex b, ref Complex result)
        {
            // (x + yi)(u + vi) = (xu ?yv) + (xv + yu)i. 
            double aRe = a.Re, aIm = a.Im;
            double bRe = b.Re, bIm = b.Im;

            result.Re = aRe * bRe - aIm * bIm;
            result.Im = aRe * bIm + aIm * bRe;
        }

        /// <summary>
        /// Multiplies a complex number by a scalar value and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        public static void Multiply(Complex a, double s, ref Complex result)
        {
            result.Re = a.Re * s;
            result.Im = a.Im * s;
        }

        /// <summary>
        /// Divides one complex number by another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result.</returns>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static Complex Divide(Complex a, Complex b)
        {
            double aRe = a.Re, aIm = a.Im;
            double bRe = b.Re, bIm = b.Im;
            double modulusSquared = bRe * bRe + bIm * bIm;

            if (modulusSquared == 0)
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }

            double invModulusSquared = 1 / modulusSquared;

            return new Complex(
                (aRe * bRe + aIm * bIm) * invModulusSquared,
                (aIm * bRe - aRe * bIm) * invModulusSquared);
        }

        /// <summary>
        /// Divides a complex number by a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result.</returns>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static Complex Divide(Complex a, double s)
        {
            if (s == 0)
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }

            return new Complex(a.Re / s, a.Im / s);
        }

        /// <summary>
        /// Divides a scalar value by a complex number.
        /// </summary>
        /// 
        /// <param name="s">A scalar value.</param>
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result.</returns>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static Complex Divide(double s, Complex a)
        {
            if ((a.Re == 0) || (a.Im == 0))
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }
            return new Complex(s / a.Re, s / a.Im);
        }

        /// <summary>
        /// Divides one complex number by another complex number and puts the result in a third complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static void Divide(Complex a, Complex b, ref Complex result)
        {
            double aRe = a.Re, aIm = a.Im;
            double bRe = b.Re, bIm = b.Im;
            double modulusSquared = bRe * bRe + bIm * bIm;

            if (modulusSquared == 0)
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }

            double invModulusSquared = 1 / modulusSquared;

            result.Re = (aRe * bRe + aIm * bIm) * invModulusSquared;
            result.Im = (aIm * bRe - aRe * bIm) * invModulusSquared;
        }

        /// <summary>
        /// Divides a complex number by a scalar value and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static void Divide(Complex a, double s, ref Complex result)
        {
            if (s == 0)
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }

            result.Re = a.Re / s;
            result.Im = a.Im / s;
        }

        /// <summary>
        /// Divides a scalar value by a complex number and puts the result into another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
        /// 
        /// <exception cref="DivideByZeroException">Can not divide by zero.</exception>
        /// 
        public static void Divide(double s, Complex a, ref Complex result)
        {
            if ((a.Re == 0) || (a.Im == 0))
            {
                throw new DivideByZeroException("Can not divide by zero.");
            }

            result.Re = s / a.Re;
            result.Im = s / a.Im;
        }

        /// <summary>
        /// Negates a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the negated values.</returns>
        /// 
        public static Complex Negate(Complex a)
        {
            return new Complex(-a.Re, -a.Im);
        }

        /// <summary>
        /// Tests whether two complex numbers are approximately equal using default tolerance value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Return <see langword="true"/> if the two vectors are approximately equal or <see langword="false"/> otherwise.</returns>
        /// 
        /// <remarks><para>The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16.</para></remarks>
        /// 
        public static bool ApproxEqual(Complex a, Complex b)
        {
            return ApproxEqual(a, b, 8.8817841970012523233891E-16);
        }


        /// <summary>
        /// Tests whether two complex numbers are approximately equal given a tolerance value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// <param name="tolerance">The tolerance value used to test approximate equality.</param>
        /// 
        /// <remarks><para>The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16.</para></remarks>
        /// 
        public static bool ApproxEqual(Complex a, Complex b, double tolerance)
        {
            return
                (
                (System.Math.Abs(a.Re - b.Re) <= tolerance) &&
                (System.Math.Abs(a.Im - b.Im) <= tolerance)
                );
        }

        #region Public Static Parse Methods
        /// <summary>
        /// Converts the specified string to its <see cref="Complex"/> equivalent.
        /// </summary>
        /// 
        /// <param name="s">A string representation of a complex number.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance that represents the complex number
        /// specified by the <paramref name="s"/> parameter.</returns>
        /// 
        /// <exception cref="FormatException">String representation of the complex number is not correctly formatted.</exception>
        /// 
        public static Complex Parse(string s)
        {
            Regex r = new Regex(@"\((?<real>.*),(?<imaginary>.*)\)", RegexOptions.None);
            Match m = r.Match(s);

            if (m.Success)
            {
                return new Complex(
                    double.Parse(m.Result("${real}")),
                    double.Parse(m.Result("${imaginary}"))
                    );
            }
            else
            {
                throw new FormatException("String representation of the complex number is not correctly formatted.");
            }
        }

        /// <summary>
        /// Try to convert the specified string to its <see cref="Complex"/> equivalent.
        /// </summary>
        /// 
        /// <param name="s">A string representation of a complex number.</param>
        /// 
        /// <param name="result"><see cref="Complex"/> instance to output the result to.</param>
        /// 
        /// <returns>Returns boolean value that indicates if the parse was successful or not.</returns>
        /// 
        public static bool TryParse(string s, out Complex result)
        {
            try
            {
                Complex newComplex = Complex.Parse(s);
                result = newComplex;
                return true;

            }
            catch (FormatException)
            {

                result = new Complex();
                return false;
            }
        }

        #endregion

        #region Public Static Complex Special Functions

        /// <summary>
        /// Calculates square root of a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the square root of the specified
        /// complex number.</returns>
        /// 
        public static Complex Sqrt(Complex a)
        {
            Complex result = Complex.Zero;

            if ((a.Re == 0.0) && (a.Im == 0.0))
            {
                return result;
            }
            else if (a.Im == 0.0)
            {
                result.Re = (a.Re > 0) ? System.Math.Sqrt(a.Re) : System.Math.Sqrt(-a.Re);
                result.Im = 0.0;
            }
            else
            {
                double modulus = a.Magnitude;

                result.Re = System.Math.Sqrt(0.5 * (modulus + a.Re));
                result.Im = System.Math.Sqrt(0.5 * (modulus - a.Re));
                if (a.Im < 0.0)
                    result.Im = -result.Im;
            }

            return result;
        }

        /// <summary>
        /// Calculates natural (base <b>e</b>) logarithm of a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the natural logarithm of the specified
        /// complex number.</returns>
        /// 
        public static Complex Log(Complex a)
        {
            Complex result = Complex.Zero;

            if ((a.Re > 0.0) && (a.Im == 0.0))
            {
                result.Re = System.Math.Log(a.Re);
                result.Im = 0.0;
            }
            else if (a.Re == 0.0)
            {
                if (a.Im > 0.0)
                {
                    result.Re = System.Math.Log(a.Im);
                    result.Im = System.Math.PI / 2.0;
                }
                else
                {
                    result.Re = System.Math.Log(-(a.Im));
                    result.Im = -System.Math.PI / 2.0;
                }
            }
            else
            {
                result.Re = System.Math.Log(a.Magnitude);
                result.Im = System.Math.Atan2(a.Im, a.Re);
            }

            return result;
        }

        /// <summary>
        /// Calculates exponent (<b>e</b> raised to the specified power) of a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the exponent of the specified
        /// complex number.</returns>
        /// 
        public static Complex Exp(Complex a)
        {
            Complex result = Complex.Zero;
            double r = System.Math.Exp(a.Re);
            result.Re = r * System.Math.Cos(a.Im);
            result.Im = r * System.Math.Sin(a.Im);

            return result;
        }
        #endregion

        #region Public Static Complex Trigonometry

        /// <summary>
        /// Calculates Sine value of the complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the Sine value of the specified
        /// complex number.</returns>
        /// 
        public static Complex Sin(Complex a)
        {
            Complex result = Complex.Zero;

            if (a.Im == 0.0)
            {
                result.Re = System.Math.Sin(a.Re);
                result.Im = 0.0;
            }
            else
            {
                result.Re = System.Math.Sin(a.Re) * System.Math.Cosh(a.Im);
                result.Im = System.Math.Cos(a.Re) * System.Math.Sinh(a.Im);
            }

            return result;
        }

        /// <summary>
        /// Calculates Cosine value of the complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the Cosine value of the specified
        /// complex number.</returns>
        /// 
        public static Complex Cos(Complex a)
        {
            Complex result = Complex.Zero;

            if (a.Im == 0.0)
            {
                result.Re = System.Math.Cos(a.Re);
                result.Im = 0.0;
            }
            else
            {
                result.Re = System.Math.Cos(a.Re) * System.Math.Cosh(a.Im);
                result.Im = -System.Math.Sin(a.Re) * System.Math.Sinh(a.Im);
            }

            return result;
        }

        /// <summary>
        /// Calculates Tangent value of the complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the Tangent value of the specified
        /// complex number.</returns>
        /// 
        public static Complex Tan(Complex a)
        {
            Complex result = Complex.Zero;

            if (a.Im == 0.0)
            {
                result.Re = System.Math.Tan(a.Re);
                result.Im = 0.0;
            }
            else
            {
                double real2 = 2 * a.Re;
                double imag2 = 2 * a.Im;
                double denom = System.Math.Cos(real2) + System.Math.Cosh(real2);

                result.Re = System.Math.Sin(real2) / denom;
                result.Im = System.Math.Sinh(imag2) / denom;
            }

            return result;
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Returns the hashcode for this instance.
        /// </summary>
        /// 
        /// <returns>A 32-bit signed integer hash code.</returns>
        public override int GetHashCode()
        {
            return Re.GetHashCode() ^ Im.GetHashCode();
        }

        /// <summary>
        /// Returns a value indicating whether this instance is equal to the specified object.
        /// </summary>
        /// 
        /// <param name="obj">An object to compare to this instance.</param>
        /// 
        /// <returns>Returns <see langword="true"/> if <paramref name="obj"/> is a <see cref="Complex"/> and has the same values as this instance or <see langword="false"/> otherwise.</returns>
        /// 
        public override bool Equals(object obj)
        {
            return (obj is Complex) ? (this == (Complex)obj) : false;
        }

        /// <summary>
        /// Returns a string representation of this object.
        /// </summary>
        /// 
        /// <returns>A string representation of this object.</returns>
        /// 
        public override string ToString()
        {
            return string.Format("({0}, {1})", Re, Im);
        }
        #endregion

        #region Comparison Operators
        /// <summary>
        /// Tests whether two specified complex numbers are equal.
        /// </summary>
        /// 
        /// <param name="u">The left-hand complex number.</param>
        /// <param name="v">The right-hand complex number.</param>
        /// 
        /// <returns>Returns <see langword="true"/> if the two complex numbers are equal or <see langword="false"/> otherwise.</returns>
        /// 
        public static bool operator ==(Complex u, Complex v)
        {
            return ((u.Re == v.Re) && (u.Im == v.Im));
        }

        /// <summary>
        /// Tests whether two specified complex numbers are not equal.
        /// </summary>
        /// 
        /// <param name="u">The left-hand complex number.</param>
        /// <param name="v">The right-hand complex number.</param>
        /// 
        /// <returns>Returns <see langword="true"/> if the two complex numbers are not equal or <see langword="false"/> otherwise.</returns>
        /// 
        public static bool operator !=(Complex u, Complex v)
        {
            return !(u == v);
        }
        #endregion

        #region Unary Operators
        /// <summary>
        /// Negates the complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/>  instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the negated values.</returns>
        /// 
        public static Complex operator -(Complex a)
        {
            return Complex.Negate(a);
        }
        #endregion

        #region Binary Operators
        /// <summary>
        /// Adds two complex numbers.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the sum.</returns>
        /// 
        public static Complex operator +(Complex a, Complex b)
        {
            return Complex.Add(a, b);
        }

        /// <summary>
        /// Adds a complex number and a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the sum.</returns>
        /// 
        public static Complex operator +(Complex a, double s)
        {
            return Complex.Add(a, s);
        }

        /// <summary>
        /// Adds a complex number and a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the sum.</returns>
        /// 
        public static Complex operator +(double s, Complex a)
        {
            return Complex.Add(a, s);
        }

        /// <summary>
        /// Subtracts one complex number from another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
        /// 
        public static Complex operator -(Complex a, Complex b)
        {
            return Complex.Subtract(a, b);
        }

        /// <summary>
        /// Subtracts a scalar value from a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
        /// 
        public static Complex operator -(Complex a, double s)
        {
            return Complex.Subtract(a, s);
        }

        /// <summary>
        /// Subtracts a complex number from a scalar value.
        /// </summary>
        /// 
        /// <param name="s">A scalar value.</param>
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
        /// 
        public static Complex operator -(double s, Complex a)
        {
            return Complex.Subtract(s, a);
        }

        /// <summary>
        /// Multiplies two complex numbers.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
        /// 
        public static Complex operator *(Complex a, Complex b)
        {
            return Complex.Multiply(a, b);
        }

        /// <summary>
        /// Multiplies a complex number by a scalar value.
        /// </summary>
        /// 
        /// <param name="s">A scalar value.</param>
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
        /// 
        public static Complex operator *(double s, Complex a)
        {
            return Complex.Multiply(a, s);
        }

        /// <summary>
        /// Multiplies a complex number by a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
        /// 
        public static Complex operator *(Complex a, double s)
        {
            return Complex.Multiply(a, s);
        }

        /// <summary>
        /// Divides one complex number by another complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="b">A <see cref="Complex"/> instance.</param>
        /// 
        /// <returns>A new Complex instance containing the result.</returns>
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of division.</returns>
        /// 
        public static Complex operator /(Complex a, Complex b)
        {
            return Complex.Divide(a, b);
        }

        /// <summary>
        /// Divides a complex number by a scalar value.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of division.</returns>
        /// 
        public static Complex operator /(Complex a, double s)
        {
            return Complex.Divide(a, s);
        }

        /// <summary>
        /// Divides a scalar value by a complex number.
        /// </summary>
        /// 
        /// <param name="a">A <see cref="Complex"/> instance.</param>
        /// <param name="s">A scalar value.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing the result of division.</returns>
        /// 
        public static Complex operator /(double s, Complex a)
        {
            return Complex.Divide(s, a);
        }
        #endregion

        #region Conversion Operators
        /// <summary>
        /// Converts from a single-precision real number to a complex number. 
        /// </summary>
        /// 
        /// <param name="value">Single-precision real number to convert to complex number.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing complex number with
        /// real part initialized to the specified value.</returns>
        /// 
        public static explicit operator Complex(float value)
        {
            return new Complex((double)value, 0);
        }

        /// <summary>
        /// Converts from a double-precision real number to a complex number. 
        /// </summary>
        /// 
        /// <param name="value">Double-precision real number to convert to complex number.</param>
        /// 
        /// <returns>Returns new <see cref="Complex"/> instance containing complex number with
        /// real part initialized to the specified value.</returns>
        /// 
        public static explicit operator Complex(double value)
        {
            return new Complex(value, 0);
        }
        #endregion

        #region ICloneable Members
        /// <summary>
        /// Creates an exact copy of this <see cref="Complex"/> object.
        /// </summary>
        /// 
        /// <returns>Returns clone of the complex number.</returns>
        /// 
        object ICloneable.Clone()
        {
            return new Complex(this);
        }

        /// <summary>
        /// Creates an exact copy of this <see cref="Complex"/> object.
        /// </summary>
        /// 
        /// <returns>Returns clone of the complex number.</returns>
        /// 
        public Complex Clone()
        {
            return new Complex(this);
        }
        #endregion

        #region ISerializable Members
        /// <summary>
        /// Populates a <see cref="SerializationInfo"/> with the data needed to serialize the target object.
        /// </summary>
        /// 
        /// <param name="info">The <see cref="SerializationInfo"/> to populate with data. </param>
        /// <param name="context">The destination (see <see cref="StreamingContext"/>) for this serialization.</param>
        /// 
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Real", this.Re);
            info.AddValue("Imaginary", this.Im);
        }
        #endregion
    }

    public static class FreqAnalyzer
    {
        /// <summary>

        /// 求复数complex数组的模modul数组

        /// </summary>

        /// <param name="input">复数数组</param>

        /// <returns>模数组</returns>

        public static double[] Cmp2Mdl(Complex[] input)
        {

            ///有输入数组的长度确定输出数组的长度

            double[] output = new double[input.Length];



            ///对所有输入复数求模

            for (int i = 0; i < input.Length; i++)
            {

                if (input[i].Re > 0)
                {

                    output[i] = -input[i].Magnitude;//.ToModul();

                }

                else
                {

                    output[i] = input[i].Magnitude;//ToModul();

                }

            }



            ///返回模数组

            return output;

        }



        /// <summary>

        /// 傅立叶变换或反变换，递归实现多级蝶形运算

        /// 作为反变换输出需要再除以序列的长度

        /// ！注意：输入此类的序列长度必须是2^n

        /// </summary>

        /// <param name="input">输入实序列</param>

        /// <param name="invert">false=正变换，true=反变换</param>

        /// <returns>傅立叶变换或反变换后的序列</returns>

        public static Complex[] FFT(double[] input, bool invert)
        {

            ///由输入序列确定输出序列的长度

            Complex[] output = new Complex[input.Length];



            ///将输入的实数转为复数

            for (int i = 0; i < input.Length; i++)
            {

                output[i] = new Complex(input[i], 0);

            }



            ///返回FFT或IFFT后的序列

            return output = FFT(output, invert);

        }



        /// <summary>

        /// 傅立叶变换或反变换，递归实现多级蝶形运算

        /// 作为反变换输出需要再除以序列的长度

        /// ！注意：输入此类的序列长度必须是2^n

        /// </summary>

        /// <param name="input">复数输入序列</param>

        /// <param name="invert">false=正变换，true=反变换</param>

        /// <returns>傅立叶变换或反变换后的序列</returns>

        private static Complex[] FFT(Complex[] input, bool invert)
        {

            ///输入序列只有一个元素，输出这个元素并返回

            if (input.Length == 1)
            {

                return new Complex[] { input[0] };

            }



            ///输入序列的长度

            int length = input.Length;



            ///输入序列的长度的一半

            int half = length / 2;



            ///有输入序列的长度确定输出序列的长度

            Complex[] output = new Complex[length];



            ///正变换旋转因子的基数

            double fac = -2.0 * Math.PI / length;



            ///反变换旋转因子的基数是正变换的相反数

            if (invert)
            {

                fac = -fac;

            }



            ///序列中下标为偶数的点

            Complex[] evens = new Complex[half];



            for (int i = 0; i < half; i++)
            {

                evens[i] = input[2 * i];

            }



            ///求偶数点FFT或IFFT的结果，递归实现多级蝶形运算

            Complex[] evenResult = FFT(evens, invert);



            ///序列中下标为奇数的点

            Complex[] odds = new Complex[half];



            for (int i = 0; i < half; i++)
            {

                odds[i] = input[2 * i + 1];

            }



            ///求偶数点FFT或IFFT的结果，递归实现多级蝶形运算

            Complex[] oddResult = FFT(odds, invert);



            for (int k = 0; k < half; k++)
            {

                ///旋转因子

                double fack = fac * k;



                ///进行蝶形运算

                Complex oddPart = oddResult[k] * new Complex(Math.Cos(fack), Math.Sin(fack));

                output[k] = evenResult[k] + oddPart;

                output[k + half] = evenResult[k] - oddPart;

            }



            ///返回FFT或IFFT的结果

            return output;

        }



        /// <summary>

        /// 频域滤波器

        /// </summary>

        /// <param name="data">待滤波的数据</param>

        /// <param name="Nc">滤波器截止波数</param>

        /// <param name="Hd">滤波器的权函数</param>

        /// <returns>滤波后的数据</returns>

        private static double[] FreqFilter(double[] data, int Nc, Complex[] Hd)
        {

            ///最高波数==数据长度

            int N = data.Length;



            ///输入数据进行FFT

            Complex[] fData = FreqAnalyzer.FFT(data, false);



            ///频域滤波

            for (int i = 0; i < N; i++)
            {

                fData[i] = Hd[i] * fData[i];

            }



            ///滤波后数据计算IFFT

            ///！未除以数据长度

            fData = FreqAnalyzer.FFT(fData, true);



            ///复数转成模

            data = FreqAnalyzer.Cmp2Mdl(fData);



            ///除以数据长度

            for (int i = 0; i < N; i++)
            {

                data[i] = -data[i] / N;

            }



            ///返回滤波后的数据

            return data;

        }

    }
}
